package com.manbu.live.user.provider.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.manbu.live.common.interfaces.emun.CommonStatusEum;
import com.manbu.live.common.interfaces.utils.ConvertBeanUtils;
import com.manbu.live.farmework.redis.starter.keys.UserProviderCacheKeyBuilder;
import com.manbu.live.id.generate.enums.IdTypeEnum;
import com.manbu.live.id.generate.interfaces.IdGenerateRpc;
import com.manbu.live.user.dto.UserLoginDTO;
import com.manbu.live.user.dto.UserPhoneDTO;
import com.manbu.live.user.provider.dao.mapper.IUserMapper;
import com.manbu.live.user.provider.dao.mapper.IUserPhoneMapper;
import com.manbu.live.user.provider.dao.po.UserPO;
import com.manbu.live.user.provider.dao.po.UserPhonePO;
import com.manbu.live.user.provider.service.IUserPhoneService;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * @author hanWang
 * @Title:
 * @Package
 * @Description:
 * @date 2024/1/284:00 AM
 */

@Service
public class UserPhoneServiceImpl implements IUserPhoneService {

    @Resource
    private IUserPhoneMapper userPhoneMapper;
    @Resource
    private IUserMapper userMapper;
    @Resource
    private RedisTemplate<String,Object> redisTemplate;
    @Resource
    private UserProviderCacheKeyBuilder keyBuilder;
    @DubboReference
    private IdGenerateRpc idGenerateRpc;

    @Override
    public UserLoginDTO login(String phone) {
        UserPhoneDTO userPhoneDTO = queryByPhone(phone);
        if (userPhoneDTO!=null){
            return UserLoginDTO.loginSuccess(userPhoneDTO.getUserId(),createAndSaveLoginToke(userPhoneDTO.getUserId()));
        }

        // 注册用户
        return register(phone);
    }

    /**
     * 注册 && 登录
     * @param phone
     * @return
     */
    private UserLoginDTO register(String phone){
        UserPO userPO = new UserPO();
        Long userId = idGenerateRpc.geSeqId(IdTypeEnum.USER_ID.getCode());
       // Long userId = 1000000L;
        userPO.setNickName("漫步直播:测试账号");
        userPO.setUserId(userId);
        userMapper.insert(userPO);
        UserPhonePO userPhonePO = new UserPhonePO();
        userPhonePO.setPhone(phone);
        userPhonePO.setStatus(CommonStatusEum.VALID_STATUS.getCode());
        userPhonePO.setUserId(userId);
        userPhoneMapper.insert(userPhonePO);
        String phoneObjKey = keyBuilder.buildUserPhoneObjKey(phone);
        redisTemplate.delete(phoneObjKey);
        return UserLoginDTO.loginSuccess(userId,createAndSaveLoginToke(userId));
    }

    @Override
    public UserPhoneDTO insert(String phone, Long userId) {
        return null;
    }

    @Override
    public List<UserPhoneDTO> queryByUserId(Long userId) {

        if (userId==null && userId<100000){
            return null;
        }
        List<UserPhoneDTO> userPhoneDTOList = queryByPhoneFromRedis(userId);

        return null;
    }
    private String createAndSaveLoginToke(Long userId){
        String token = UUID.randomUUID().toString();
        String loginTokenKey = keyBuilder.buildUserLoginTokenKey(token);
        redisTemplate.opsForValue().set(loginTokenKey,token,30, TimeUnit.DAYS);
        return  token;
    }

    @Override
    public UserPhoneDTO queryByPhone(String phone) {
        if (StringUtils.isEmpty(phone)){
            return null;
        }
        String phoneObjKey = keyBuilder.buildUserPhoneObjKey(phone);
        UserPhoneDTO userPhoneDTO = (UserPhoneDTO) redisTemplate.opsForValue().get(phoneObjKey);
        if (userPhoneDTO == null){
            userPhoneDTO = queryByPhoneFromDB(phone);
            if (userPhoneDTO!=null){
                if (userPhoneDTO.getUserId() ==null){
                    redisTemplate.opsForValue().set(phoneObjKey,userPhoneDTO,5,TimeUnit.MINUTES);
                    return null;
                }
                redisTemplate.opsForValue().set(phoneObjKey,userPhoneDTO,30,TimeUnit.MINUTES);
                return userPhoneDTO;
            }
        }
        userPhoneDTO = new UserPhoneDTO();
        // 缓存击穿 数据库和db 都没有的情况下
        redisTemplate.opsForValue().set(phoneObjKey,userPhoneDTO,5,TimeUnit.MINUTES);
        return null;
    }


    private List<UserPhoneDTO> queryByPhoneFromRedis(Long userId) {
        if (userId==null){
            return Collections.emptyList();
        }
        String phoneObjKey = keyBuilder.buildUserPhoneListKey(userId);
        List<Object> userPhoneDTOList =  redisTemplate.opsForList().range(phoneObjKey,0,-1);
        if (CollectionUtils.isEmpty(userPhoneDTOList)){
            List<UserPhoneDTO> userPhoneDTOList1 = queryByUserIdListFromDB(userId);
            if (!CollectionUtils.isEmpty(userPhoneDTOList)){
                redisTemplate.opsForList().leftPushAll(phoneObjKey,userPhoneDTOList.toArray(),30,TimeUnit.MINUTES);
                return userPhoneDTOList.stream().map(a->(UserPhoneDTO)a).collect(Collectors.toList());
            }
        }else {
            if (((UserPhoneDTO)userPhoneDTOList.get(0)).getUserId()!=null){
                return userPhoneDTOList.stream().map(a->(UserPhoneDTO)a).collect(Collectors.toList());
            }
        }

        userPhoneDTOList = Arrays.asList(new UserPhoneDTO());
        // 缓存击穿 数据库和db 都没有的情况下
        redisTemplate.opsForList().leftPushAll(phoneObjKey,userPhoneDTOList.toArray(),5,TimeUnit.MINUTES);
        return Collections.emptyList();
    }

    private UserPhoneDTO queryByPhoneFromDB(String phone) {
        LambdaQueryWrapper<UserPhonePO> userPOLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userPOLambdaQueryWrapper.eq(UserPhonePO::getPhone,phone);
        userPOLambdaQueryWrapper.eq(UserPhonePO::getStatus, CommonStatusEum.VALID_STATUS.getCode());
        userPOLambdaQueryWrapper.last("limit 1");
        UserPhonePO userPhonePO = userPhoneMapper.selectOne(userPOLambdaQueryWrapper);
        if (userPhonePO != null){
            return ConvertBeanUtils.convert(userPhonePO,UserPhoneDTO.class);
        }
        return null;
    }

    private List<UserPhoneDTO> queryByUserIdListFromDB(Long userId) {
        LambdaQueryWrapper<UserPhonePO> userPOLambdaQueryWrapper = new LambdaQueryWrapper<>();
        userPOLambdaQueryWrapper.eq(UserPhonePO::getUserId,userId);
        userPOLambdaQueryWrapper.eq(UserPhonePO::getStatus, CommonStatusEum.VALID_STATUS);
        return ConvertBeanUtils.convertList(userPhoneMapper.selectList(userPOLambdaQueryWrapper),UserPhoneDTO.class);
    }
}
